/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c), 2003-2011,  Jin Chen and Alan M. MacEachren, GeoVISTA Center, Penn State University
 * Licensed under Simplified BSD License
 *
 *
 * @author: jin Chen 
 * @date: Nov 17, 2005$
 * @version: 1.0
 */
package edu.psu.geovista.app.gmatrix;

import edu.psu.geovista.app.gmatrix.canvas.Cell;
import edu.psu.geovista.app.gmatrix.canvas.DfCell;
import edu.psu.geovista.app.gmatrix.canvas.DfMatrixCanvas;
import edu.psu.geovista.app.gmatrix.canvas.MatrixCanvasContext;
import edu.psu.geovista.app.gmatrix.component.DfMatrixCorner;
import edu.psu.geovista.app.gmatrix.component.DfMatrixHeader;
import edu.psu.geovista.app.gmatrix.component.MatrixHeader;
import edu.psu.geovista.app.gmatrix.control.DfSelectMgr;
import edu.psu.geovista.app.gmatrix.data.BasicMatrixmodel;
import edu.psu.geovista.app.gmatrix.data.DfMatrixModel;
import edu.psu.geovista.app.gmatrix.data.DfSelectionModel;
import edu.psu.geovista.app.gmatrix.data.Matrixmodel;
import edu.psu.geovista.app.gmatrix.toolkit.FireEventSupport;
import edu.psu.geovista.app.gmatrix.toolkit.MatrixLoggerMgr;
import edu.psu.geovista.app.gmatrix.toolkit.MatrixUtils;
import edu.psu.geovista.app.gmatrix.toolkit.TableModelSupport;
import edu.psu.geovista.app.gmatrix.ui.DfMatrixUI;
import edu.psu.geovista.app.vit.pub.utils.VitUtils;
import edu.psu.geovista.ui.event.IndicationEvent;
import edu.psu.geovista.ui.event.IndicationListener;
import edu.psu.geovista.ui.event.SelectionEvent;
import edu.psu.geovista.ui.event.SelectionListener;
import layout.TableLayout;

import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class JDfMatrix extends JPanel
                     implements IndicationListener , SelectionListener {  //, Application
    private static final Logger logger=Logger.getLogger(JDfMatrix.class.getName());
    //data
    BasicMatrixmodel datamodel;  //data model
    DfSelectionModel selectmodel; //selection model
    //tool
    protected FireEventSupport eventfirer;
    TableModelSupport tablesupport; // 
    MyDataListener dataListener;
    //component
    protected DfMatrixCanvas canvas;
    protected DfMatrixCorner corner;
    protected MatrixHeader rowheader;
    protected MatrixHeader columnheader;
    protected DfMatrixUI UIcontrol;//todo temp ui, need use UIComponent
    protected DfSelectMgr selectMgr;


    public JDfMatrix() {

        this(100, 100);//todo need figure out how to set it runtime
    }

    public JDfMatrix(int rowHeaderWidth, int columnHeaderHight) {
        initstart();
        initComponent( columnHeaderHight, rowHeaderWidth);
        initend(); //must appear after   initComponent(), need component to do setup
    }
    /*******************************************************************************************************
     *                setup
     *******************************************************************************************************/
    /**
     *
      * @param nbrow   # of row
     * @param nbcol
     */
    public void setRowColumn( int nbrow, int nbcol){
        datamodel.setRowColumn(nbrow,nbcol);
        canvas.resetLayout();
        //this.canvas.setRowColumn(row,col);
    }
    public void setColors(Color[][] colors) {
        datamodel.setColors(colors);
        canvas.resetLayout();
        //this.canvas.setColors(colors);
    }
     public void setColors(Color[] colors) {

        datamodel.setColors(colors);
        canvas.resetLayout();
        //repaint();
    }
    public void setRownames(String[] rownames) {
        datamodel.setRowIdentifiers(rownames);
       // this.rowheader.setCelllabels(rownames);

    }

    public void setColnames(String[] colnames) {
        //this.columnheader.setCelllabels(colnames);
        this.datamodel.setColumnIdentifiers(colnames);

    }

    public void setGridSize(int hgap, int vgap) {
        this.canvas.setGridSize(hgap,vgap);
    }
    /**************************************************
     *                inits
     ***************************************************/
    /**
     * init before initcomponent to generate tools for components
     */
    protected void initstart(){
         this.selectmodel=new DfSelectionModel();
         UIcontrol = getUIcontrol();//new DfMatrixUI(this);
    }
    /**
     * init after initcomponent to access components
     */
    protected void initend(){
        UIcontrol.setupEnd();//this line need in initend. UIcontrol must instantiate after canvas available
        setupEvents();
        eventfirer =new FireEventSupport(this);

        if (this.datamodel instanceof DefaultTableModel) {
            DefaultTableModel tm = (DefaultTableModel) this.datamodel;
            this.tablesupport =new TableModelSupport(this,tm);
            dataListener=new MyDataListener();
            tm.addTableModelListener(dataListener);
        }
    }
    protected void setupEvents(){
        // 
        DfSelectionModel selectmodel = getSelectmodel();
        DfMatrixUI ui = this.getUIcontrol();
        DfSelectMgr selectMgr = this.getSelectMgr();
        selectmodel.addMatrixSelectionChangeListener(selectMgr);

        //register internal selection src.
        //canvas
        DfMatrixCanvas canvas = this.getCanvas();
        canvas.addMatrixIndicationChangeListener(ui);
        canvas.setSelectClient(selectMgr);
        //canvas.addMatrixSelectionChangeListener(ui);


        //selectmodel.addMatrixSelectionChangeListener(canvas);

        //row header
        MatrixHeader rowheader = this.getRowheader();
        rowheader.setSelectclient(selectMgr);
        //selectmodel.addMatrixSelectionChangeListener((MatrixSelectionListener) rowheader);
        //col header
        MatrixHeader columnheader = this.getColumnheader();
        columnheader.setSelectclient(selectMgr);
       // selectmodel.addMatrixSelectionChangeListener((MatrixSelectionListener) columnheader);

    }
    protected DfMatrixUI getUIcontrol(){
        if(UIcontrol==null){
              UIcontrol = new DfMatrixUI(this);
        }
        return  UIcontrol ;
    }

    protected DfSelectMgr getSelectMgr(){
        if(this.selectMgr==null){
            selectMgr=new DfSelectMgr(this);
        }
        return selectMgr;
    }

    /**
     *
     * @param columnHeaderHight  height of the column header panel
     * @param rowHeaderWidth     width of the row  header panel
     */
    protected  void initComponent(int columnHeaderHight, int rowHeaderWidth){

        canvas=getDefaultCanvas();


        JLabel colRd = getDefaultCellRender();

        columnheader=new DfMatrixHeader(columnHeaderHight, SwingConstants.HORIZONTAL );
        columnheader.setCellrender(colRd);

        JLabel rowRd = getDefaultCellRender();
        //rowRd.setBorder(BorderFactory.createLineBorder(Color.RED ) );
        rowheader=new DfMatrixHeader(rowHeaderWidth, SwingConstants.VERTICAL);
        rowheader.setCellrender(rowRd);


        layout(rowHeaderWidth, columnHeaderHight);
        // this.add(canvas);

    }

    protected void layout(int rowHeaderWidth, int columnHeaderHight) {
        //todo move to UI
        JPanel mainp=new JPanel();
        JPanel controlp=new JPanel();
        double size[][]={{rowHeaderWidth, TableLayout.FILL },{columnHeaderHight,   TableLayout.FILL}};

        mainp.setLayout(new TableLayout(size));
        mainp.add(new JPanel(),"0,0");
        mainp.add(canvas,"1,1");
        mainp.add((JComponent)columnheader,"1,0");
        mainp.add((JComponent) rowheader,"0,1");


        PropertyChangeListener pl=new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent evt) {
                double[] aRowCenter = canvas.getRowCenters();
                double[] aColumnCenter = canvas.getColumnCenters();
               // logger.fine("jmatrix");
                  if(logger.isLoggable(Level.FINER )){
                      showCenter(aRowCenter);
                      showCenter(aColumnCenter);
                  }
                columnheader.setCellcenters(aRowCenter);
                rowheader.setCellcenters(aColumnCenter);
                JDfMatrix.this.repaint();// 
            }
        } ;
        canvas.addPropertyChangeListener(pl);

     /*   ActionMgr actionMgr = (ActionMgr) this.getActionMgr();
        JMenuBar menubar = actionMgr.getMenubar();

        controlp.setLayout(new BorderLayout());
        controlp.add(menubar);*/
        //controlp.add(new JLabel("control pane"));

        setLayout(new BorderLayout());
        this.add(mainp);
        this.add(controlp,BorderLayout.NORTH );
    }

    private void showCenter(double[] centers){
        if(centers!=null&&centers.length >2)
        System.out.println(" center distance:"+(centers[1]-centers[0]));
        for (int i=0;i<centers.length ;i++){
            System.out.print(centers[i]+",");
        }
        System.out.println("");
    }

    protected  JLabel getDefaultCellRender(){
        JLabel cellrender=new JLabel();
        cellrender.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY ) );
        cellrender.setHorizontalAlignment(SwingConstants.CENTER );
        cellrender.setFont(new Font("Arial",Font.BOLD ,12));
        cellrender.setHorizontalAlignment(SwingConstants.CENTER );
        return cellrender;
    }

    protected  DfMatrixCanvas getDefaultCanvas(){

        this.datamodel =new DfMatrixModel() ;
        datamodel.setRowColumn(10,5);
        final DfMatrixCanvas sp=new DfMatrixCanvas(datamodel);
        sp.setLayouttype(MatrixCanvasContext.LAYOUT_TOP_BOTTOM);
        sp.setBackground(Color.black );
        sp.setGridSize(2,2);

        sp.setGridlineColor(Color.white );
        return sp;
    }

    /*******************************************************************************************************
     *                service

     *******************************************************************************************************/
    /**************************************************
     *                selection/highlight                                            
     ***************************************************/
    /**
     *
     * @param matrixIndexs
     */
    public void select(Set<Point> matrixIndexs){
        this.selectmodel.setSelection(matrixIndexs);
        logger.fine(" ");
        MatrixLoggerMgr.fine(logger," Select cells "+matrixIndexs.size() );
        if(logger.isLoggable(Level.FINE ) )    {
            MatrixUtils.print(matrixIndexs,"        ");
        }
        //this.selectmodel.setSelectRows(this.getRowsOfCells(matrixIndexs));
         //this.selectmodel.setSelectCols(this.getColumnsOfCells(matrixIndexs));

    }
    public void addSelect(Set<Point> matrixIndexs){
        this.selectmodel.addSelection(matrixIndexs);
        logger.fine(" ");
        MatrixLoggerMgr.fine(logger," add select cells "+matrixIndexs.size() );
        if(logger.isLoggable(Level.FINE ) )    {
            MatrixUtils.print(matrixIndexs,"        ");
        }
        //this.selectmodel.setSelectRows(this.getRowsOfCells(matrixIndexs));
         //this.selectmodel.setSelectCols(this.getColumnsOfCells(matrixIndexs));

    }
    public void removeSelect(Set<Point> matrixIndexs){
        this.selectmodel.removeSelection(matrixIndexs);
        logger.fine(" ");
        MatrixLoggerMgr.fine(logger," add select cells "+matrixIndexs.size() );
        if(logger.isLoggable(Level.FINE ) )    {
            MatrixUtils.print(matrixIndexs,"        ");
        }
        //this.selectmodel.setSelectRows(this.getRowsOfCells(matrixIndexs));
         //this.selectmodel.setSelectCols(this.getColumnsOfCells(matrixIndexs));

    }
    public void highlight(Point matrixIndex){
        this.canvas.showHighlight(matrixIndex);
    }
    /*public void selectRow(int rowIndex){
        canvas.selectRow(rowIndex, false);
    }*/
    public void selectRow(int[] rowIndexs){
        Set<Point> rowsSelection = getCellsByRows(rowIndexs);
        select(rowsSelection);
        //canvas.selectRow(rowIndexs, false);
    }
    public void selectColumn(int[] colIndexs){
        Set<Point> colSelection = this.getCellsByColumns(colIndexs);
        select(colSelection);
    }


    /**************************************************
     *                add row/columns
     ***************************************************/

    public void addRow(Object rowname, Vector <Cell> rowdata){
        ((DfMatrixModel)this.datamodel).addRow(rowname,rowdata);
         this.canvas.resetLayout();//todo use event model
    }
    /**
     *
     * @param rowname
     * @param colors
     */
    public void addRow(Object rowname, Color[] colors){
       if (!(datamodel instanceof Matrixmodel)) {
             new IllegalArgumentException(this.getClass().getName() +"current datamodel not support adding");
       }
        Vector cells = createCells( colors);
       ((DfMatrixModel)this.datamodel).addRow(rowname,cells);
        this.canvas.resetLayout();//todo use event model

    }
    public void addRows(Object[] rownames, Color[][] colors){
        int nbrow = colors.length;
        //int nbcol = colors[0].length;
        for (int i=0;i<nbrow;i++){
            Color[] arow = colors[i];
             Vector cells = createCells( arow);
             Object rowname=null;
             if(rownames!=null){
                 rowname=rownames[i];
             }
            ((DfMatrixModel)this.datamodel).addRow(rowname,cells);
        }
          this.canvas.resetLayout();//todo use event model
    }
     public static Vector <Cell> createCells( Color[] colors) {
        int nbcol=colors.length ;
        //Cell[] cells=new Cell[nbcol];
        Vector cells=new Vector(nbcol);
        for (int i=0;i<nbcol;i++){
            DfCell cell = new DfCell();
            cell.setForeground(colors[i]);
            cells.add(cell);
        }
        return cells;
    }

    public void removeRow(int row){
        if (!(datamodel instanceof Matrixmodel)) {
             new IllegalArgumentException(this.getClass().getName() +"current datamodel not support adding");
       }
       ((DfMatrixModel)this.datamodel).removeRow(row);
        this.canvas.resetLayout();//todo use event model
    }
    public void removeRows(int[] rows){
        Arrays.sort(rows);
        for (int i=rows.length -1;i>=0;i--){
            ((DfMatrixModel)this.datamodel).removeRow(rows[i]);
        }
         this.canvas.resetLayout();//todo use event model
    }
      /**************************************************
     *                operate on rows
     ***************************************************/
    /**
     *
      * @param row
     */
    public void moveTop(int row) {
        ((DefaultTableModel)this.datamodel).moveRow(row,row,0);
        repaint();
    }
    public void moveTop(int[] rows) {
        Arrays.sort(rows);
        for (int i=0;i<rows.length ;i++){
            moveTop(rows[i]);
        }
        repaint();

    }
    public void moveBottom(int row) {
        int rowNumber=datamodel.getNumOfRow();
        ((DefaultTableModel)this.datamodel) .moveRow(row,row,rowNumber-1);
        repaint();
    }
    public void moveBottom(int[] rows) {
        Arrays.sort(rows);
        for (int i=rows.length -1;i>=0;i--){
            moveBottom(rows[i]);
        }
        repaint();
    }

    public void moveRowUp(int row) {
        boolean valid = this.moveRow(row, true);
        if(valid){
            int nextRow = this.getNextRow(row, true);
            canvas.selectRow(nextRow, false);
        }
        repaint();
    }
    public void moveRowDown(int row) {
        boolean valid =this.moveRow(row,false);
        if(valid){
            int nextRow = this.getNextRow(row, false);
            canvas.selectRow(nextRow, false);
        }
        repaint();
    }
    /**
     * Move multiple rows up
     * @param rows  the index of the rows which is to move up
     */
    public void moveRowsUp(int[] rows) {
        boolean up=true;
        Arrays.sort(rows);
        // 
        // 
        //Set valids=new HashSet();
        for (int i=0;i<rows.length ;i++){
            boolean valid = this.moveRow(rows[i], up);
            if(valid){  //move it
                rows[i]=this.getNextRow(rows[i],up);
            }
            else{
               //do nothing, not move
            }
        }

        updateSelectionOnMoving(rows);
        repaint();
    }

    /**
     * update upon move up/down rows
     * @param rows
     */
    private void updateSelectionOnMoving(int[] rows) {
        //Keep selection.
        // get unique values
        Set valids=new HashSet();
        for (int i=0;i<rows.length ;i++){
            valids.add(rows[i]);
        }
        if (valids.size() >0){
            int[] validrows = VitUtils.convert2IntArray(valids);
            //this.selectmodel.setSelectRows(validrows);
            this.selectRow(validrows);
             //canvas.selectRow(validrows, false);
        }
    }

    public void moveRowsDown(int[] rows) {
        boolean up=false;
        Arrays.sort(rows);
        //For down, move larger index first, then move smaller index
        for (int i=rows.length-1;i>=0 ;i--){
            boolean valid = this.moveRow(rows[i], up);
             if(valid){  //move it
                rows[i]=this.getNextRow(rows[i],up);
            }
              else{
               //do nothing, not move
            }
        }
       updateSelectionOnMoving(rows);
       repaint();
    }
    /**
     * move selected up
      */
    public void moveRowUp() {
        int[] rows = canvas.getSelectedRows();
        if(rows.length >0){
            moveRowsUp(rows);
        }
    }
    /**
     * move selected down
      */
    public void moveRowsDown() {
        int[] rows = canvas.getSelectedRows();
        if(rows.length >0){
            moveRowsDown(rows);
        }
    }
     /**
     *
     * @param row
     * @param up
     */
    public  boolean moveRow(int row,boolean up) {
        DefaultTableModel tablemodel= (DefaultTableModel) datamodel;
        if(up&&row<=0) return false;//unable to move up anymore
         int rowCount = tablemodel.getRowCount();
         if(!up&&(row<0||row>=rowCount -1 )){
             //this.getRowCount()-1 is last row, can't be moved down
             return false;//unable to move down anymore
         }

         boolean valid = validMoving(row, rowCount, up);
         if(valid){
             if(up){
                 tablemodel.moveRow(row,row,row-1);
             }
             else{
                  tablemodel.moveRow(row,row,row+1);
             }
         }
         return valid;
         //repaint();
    }
    protected boolean validMoving(int row,int rowcount,boolean up){
        boolean valid=true;
        int nextrow=0;
        if(up){
                nextrow=row-1;
                if(nextrow<0)
                    valid=false;//attemp to negative row  , invalid
            }
            else{//down
                nextrow=row+1;
                if(nextrow>=rowcount)
                    valid=false;//attemp to negative row  , invalid
            }


        return valid;

    }
    protected int[] getNextRows(int rows[], boolean up){
        for (int i=0;i<rows.length;i++){
            rows[i]=getNextRow(rows[i],up);
        }
        return rows;
    }
    protected int getNextRow(int row,boolean up){
       int delta;
        if(up)delta=-1;
        else delta=1;
        int nextrow = row + delta;

        return nextrow;
    }

    /*******************************************************************************************************
     *                support
     *******************************************************************************************************/

    /**
     *
     * @param rowIndexs    row indexs
     * @return      cells index of the rows
     */
     public  Set<Point> getCellsByRows(int[] rowIndexs) {
        int nbOfColumn=this.getNumOfColumn();
        int total=nbOfColumn*rowIndexs.length ;
        Set <Point> selects=new HashSet<Point>(total);
        //Point selects[]=new Point[nbOfColumn];
        for (int i =0;i <rowIndexs.length ;i++){
            //System.out.println("Select row:"+rowIndexs[i]);
            for (int col =0;col <nbOfColumn;col++){
                Point cell = new Point(rowIndexs[i], col);
                selects.add(cell);
            }
        }
        return selects;
    }

    /**
     *
     * @param colIndexs     column indexs
     * @return              cells index of the column
     */
     public  Set<Point> getCellsByColumns(int[] colIndexs) {
        int nbOfrow =this.getNumOfRow();
         int total=nbOfrow*colIndexs.length ;
        Set <Point> selects=new HashSet<Point>(total);
        for (int i=0;i<colIndexs.length ;i++){

        for (int row =0;row <nbOfrow;row++){
            Point cell = new Point(row,colIndexs[i]);
            selects.add(cell);

        }
        }
        return selects;
    }

    /**
     *
     * @param cells  cells
     * @return      rows that involved with the given cells. The rows is sorted
     */
    public int[] getRowsOfCells(Set<Point> cells){
        Set rowset=new HashSet();
        for (Iterator iterator = cells.iterator(); iterator.hasNext();) {
            Point cellIndex = (Point) iterator.next();
            int row = cellIndex.x;
            rowset.add(row);
        }
        int[] rows = VitUtils.convert2IntArray(rowset);
        Arrays.sort(rows);
        return rows;
    }
    /**
     *
     * @param cells  cells
     * @return      rows that involved with the given cells
     */
    public int[] getColumnsOfCells(Set<Point> cells){
        Set colset =new HashSet();
        for (Iterator iterator = cells.iterator(); iterator.hasNext();) {
            Point cellIndex = (Point) iterator.next();
            int col = cellIndex.y;
            colset.add(col);
        }
        int[] cols = VitUtils.convert2IntArray(colset);
        return cols;
    }
     public double[] getRowCenters(){
         return this.canvas.getRowCenters();
     }
     public double[] getColCenters(){
         return this.canvas.getColumnCenters();
     }

    public int convert2Id(Point p){
       //logger.warning(" The method is not implemented yet. ");
          MatrixLoggerMgr.fine(logger," The method is not implemented yet. ");
       return 0;
    }

  
    public int[] convert2Ids(Set<Point> ps){
        //logger.warning(" The method is not implemented yet. ");
        MatrixLoggerMgr.fine(logger," The method is not implemented yet. ");
        return new  int[0];
    }
    /*******************************************************************************************************
     *                getter/setter
     *******************************************************************************************************/
    /**
     *
     * @return a
     */
    public MatrixHeader getColumnheader() {
        return columnheader;
    }

    public MatrixHeader getRowheader() {
        return rowheader;
    }

    public DfMatrixCanvas getCanvas() {
        return canvas;
    }

    public DfMatrixCorner getCorner() {
        return corner;
    }

    public String[] getRownames() {
        DfMatrixModel datamodel = (DfMatrixModel) this.datamodel;
        return (datamodel).getRowNames(); //this.rowheader.getCelllabels();
    }
    public String getRowName(int index){
        String[] rownames = this.getRownames();
        if(rownames.length >index)   {
            return rownames[index];
        }
        else{
            return "";
        }
    }
    public int getRowIndexByName(String rowname){
        String[] rownames = this.getRownames();
        return getIndex(rownames,rowname);
    }
    public int getColumnIndexByName(String rowname){
        String[] colnames = this.getColnames();
        return getIndex(colnames,rowname);
    }
    public static int getIndex(Object[] objs,Object obj){
        for (int i=0;i<objs.length ;i++){
            if(objs[i].equals(obj) ){
                return i;
            }
        }
        return -1;
    }
    public String[] getColnames() {
         return this.columnheader.getCelllabels();
    }

    public int getNumOfRow(){
        //return this.canvas.getNumOfRow();
       return  this.datamodel.getNumOfRow();
    }
    public int getNumOfColumn(){
        //return this.canvas.getNumOfCulumn();
        return datamodel.getNumOfCulumn();
    }

    public DfSelectionModel getSelectmodel() {
        return selectmodel;
    }

    /**
     *  
     * @param actmap
     */
    public void setCanvasPopupAction(Map actmap){
        this.canvas.setPopupAction(actmap);
    }
    /*******************************************************************************************************
      *                events
      *******************************************************************************************************/
    /**
     * adds an SelectionListener
     */
    public void addSelectionListener (SelectionListener l) {
       eventfirer.addListener(SelectionListener.class, l);
    }

    /**
     * removes an SelectionListener from the component
     */
    public void removeSelectionListener (SelectionListener l) {
        eventfirer.removeListener(SelectionListener.class, l);
    }

    /**
     * adds an IndicationListener
     */
    public void addIndicationListener(IndicationListener l) {
        eventfirer.addListener(IndicationListener.class, l);

    }

    /**
     * removes an IndicationListener from the component
     */
    public void removeIndicationListener(IndicationListener l) {
        eventfirer.removeListener(IndicationListener.class, l);
    }
    public  void fireSelectionChanged ( Set <Point> newSelection) {
        int[] selection = this.convert2Ids(newSelection);
        eventfirer.fireSelectionChanged(selection);
    }
    public  void fireIndicationChanged (Point indicator) {
        int indict = this.convert2Id(indicator);
        eventfirer.fireIndicationChanged(indict);
    }



    public void indicationChanged(IndicationEvent indicationEvent) {
        //this.evtfirer.addListener();
    }

    public void selectionChanged(SelectionEvent selectionEvent) {
        //To change body of implemented methods use File | Settings | File Templates.
    }
    /*******************************************************************************************************
     *                frame
     *******************************************************************************************************/

    public int[] getSelectedRows(){

        return this.canvas.getSelectedRows() ;
    }

    public Set<Point> getSelectedCells(){
        return canvas.getSelectedCell();
    }
    public BasicMatrixmodel getDatamodel() {
        return datamodel;
    }

    public static Set<Point> getFullSelection(int rowCount, int colCount) {
        Set selection=new HashSet(rowCount*colCount);
        for (int i=0;i<rowCount ;i++){

            for (int j=0;j<colCount;j++){
                Point p=new Point(i,j);
                selection.add(p);
            }
        }
        return selection;
    }

    /**
     * listen to update on datamodel
     */
    class MyDataListener implements TableModelListener {

        public void tableChanged(TableModelEvent e) {
            String[] rownames = ((DfMatrixModel) datamodel).getRowNames();
             String[] colnames = ((DfMatrixModel) datamodel).getColumnNames();
            rowheader.setCelllabels(rownames);//
            columnheader.setCelllabels(colnames);
            //for highlight
            canvas.setRownames(rownames);
            canvas.setColnames(colnames);

            //
            JDfMatrix matrix = JDfMatrix.this;

            DfSelectionModel selectmodel = matrix.getSelectmodel();
            selectmodel.setRowCount(matrix.getNumOfRow());
            selectmodel.setColCount(matrix.getNumOfColumn());

        }
    }




}               /*  public void addRow(Color[] colors){
         this.canvas.addRow(colors);
         this.repaint();
    }
     public void addRows(Color[][] colors){
         this.canvas.addRows(colors);
         this.repaint();
     }
     public void removeRow(int row){
         this.canvas.removeRow(row);
         this.repaint();
     }
    public void removeRows(int[] rows){
        canvas.removeRows(rows);
        this.repaint();
    }
    public void addColumn(Color[] colors){
        this.canvas.addColumn(colors);
        this.repaint();

    }*/

 /*******************************************************************************************************
    *                add/remove
    *******************************************************************************************************/
